package com.lottery.system.service.activitystatus.impl;

import com.lottery.system.common.errorcode.ServiceErrorCodeConstants;
import com.lottery.system.common.exception.ServiceException;
import com.lottery.system.service.ActivityService;
import com.lottery.system.service.DrawPrizeService;
import com.lottery.system.service.activitystatus.ActivityStatusManager;
import com.lottery.system.service.activitystatus.enums.SequenceEnum;
import com.lottery.system.service.activitystatus.operater.ActivityStatusAbstractOperator;
import com.lottery.system.service.dto.ConvertActivityDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @author: xiaoxie
 * create: 2024-09-12 18:24
 * @BelongsProject: lottery-system
 * @BelongsPackage: com.lottery.system.service.activitystatus.impl
 * description: 活动状态管理实现类
 */
@Component
public class ActivityStatusManagerImpl implements ActivityStatusManager {
    private final static Logger logger = LoggerFactory.getLogger(ActivityStatusManagerImpl.class);
    @Autowired
    private final  Map<String, ActivityStatusAbstractOperator> statusManagerMap = new HashMap<String,ActivityStatusAbstractOperator>();
    @Autowired
    private DrawPrizeService drawPrizeService;
    @Autowired
    private ActivityService activityService;
    /**
     * @description: 活动状态处理
     * @author: xiaoxie
     * @date: 2024/9/12 18:24
     * @param: [convertActivityDTO]
     * @return: void
     **/
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handleEvent(ConvertActivityDTO convertActivityDTO) {
        if(null == convertActivityDTO) {
            logger.error("convertActivityDTO is null");
            return;
        }
        //处理依赖问题
        //1.责任链设计模式(定死每个模块的先后顺序)
        //2.策略模式设计模式(设计一个接口,在定义需要改变状态的几个类,在每个类实现不一样的策略.)
        //先处理,人员,奖品状态
        Map<String,ActivityStatusAbstractOperator> currMap =  new HashMap<>(statusManagerMap);
        //是否扭转状态的标志位
        Boolean update = false;
        update = convertStatus(convertActivityDTO,SequenceEnum.BEFORE,currMap);
        //后处理活动状态
        update = convertStatus(convertActivityDTO,SequenceEnum.AFTER,currMap) || update;
        //缓存
        if(update) {
            //缓存
           activityService.cacheWinningInfo(convertActivityDTO.getActivityId());
        }
    }

    /**
     * @description: 回滚扭转状态
     * @author: xiaoxie
     * @date: 2024/9/15 21:27
     * @param: [convertActivityDTO]
     * @return: void
     **/
    @Override
    public void rollBackHandleEvent(ConvertActivityDTO convertActivityDTO) {
        if(null == convertActivityDTO) {
            logger.error("rollBackHandleEvent : convertActivityDTO is null");
            return;
        }
        //扭转状态 简单策略模式
        for(ActivityStatusAbstractOperator map : statusManagerMap.values()) {
            map.convertStatus(convertActivityDTO);
        }
        //更新缓存
        activityService.cacheWinningInfo(convertActivityDTO.getActivityId());
    }

    /**
     * @description: 缓存状态
     * @author: xiaoxie
     * @date: 2024/9/12 20:26
     * @param: [convertActivityDTO, i, currMap]
     * @return: java.lang.Boolean
     **/
    private Boolean convertStatus(ConvertActivityDTO convertActivityDTO,
                                  SequenceEnum sequence,
                                  Map<String,ActivityStatusAbstractOperator> currMap) {
        //标志位
        Boolean update = false;
        //先根据迭代器判断是需要扭转那个状态
        Iterator<Map.Entry<String, ActivityStatusAbstractOperator>> iterator = currMap.entrySet().iterator();
        while(iterator.hasNext()) {
        //判断扭转那个状态
            ActivityStatusAbstractOperator operator = iterator.next().getValue();
            if (null == operator) {
                logger.warn(ServiceErrorCodeConstants.ACTIVITY_STATUS_ERROR.getMsg());
                throw new ServiceException(ServiceErrorCodeConstants.ACTIVITY_STATUS_ERROR);
            }
            if(!operator.sequence().equals(sequence)) {
                continue;
            }
            //判断是否需要扭转
            if(!operator.needConvert(convertActivityDTO)) {
                return false;
            }
            //开始扭转
            if(!operator.convertStatus(convertActivityDTO)) {
                logger.warn(ServiceErrorCodeConstants.ACTIVITY_STATUS_ERROR.getMsg());
                throw new ServiceException(ServiceErrorCodeConstants.ACTIVITY_STATUS_ERROR);
            }
            update = true;
            iterator.remove();
        }
        return update;
    }
}
